from PyQt5.QtCore import QThread, pyqtSignal
import numpy as np
import requests
import io
import pickle
from config import SERVER_URL, SERVER_HEALTH_URL
from core.segmentation_methods import PointCloudSegmentor, SegmentationMethod  
from core.reconstruction_methods import PointCloudReconstructor, ReconstructionMethod  # 导入新工具类
import open3d as o3d

class CompletionThread(QThread):
    """点云补全线程（调用服务器接口）"""
    completion_finished = pyqtSignal(np.ndarray , str)  # 成功信号（返回补全点云）
    completion_error = pyqtSignal(str)            # 错误信号（返回错误信息）

    def __init__(self, point_cloud_data):
        super().__init__()
        self.point_cloud_data = point_cloud_data  # 输入点云（N×3）

    def run(self):
        try:
            # 1. 检查服务器健康状态
            print("正在检查服务器健康状态...")
            health_response = requests.get(SERVER_HEALTH_URL, timeout=5)
            if health_response.status_code != 200:
                self.completion_error.emit(f"服务器健康检查失败：{health_response.status_code} - {health_response.text}")
                return

            # 2. 序列化点云数据
            buffer = io.BytesIO()
            pickle.dump(self.point_cloud_data, buffer)
            buffer.seek(0)  # 重置文件指针到开头

            # 3. 发送POST请求到服务器
            print(f"发送点云到服务器（形状：{self.point_cloud_data.shape}）...")
            files = {'point_cloud': buffer.getvalue()}
            response = requests.post(SERVER_URL, files=files, timeout=6000)  # 10分钟超时

            # 4. 处理服务器响应
            if response.status_code == 200:
                completed_pc = pickle.load(io.BytesIO(response.content))
                print("点云补全成功，接收结果...")
                self.completion_finished.emit(completed_pc , "点云补全结果")
            else:
                error_msg = response.json().get('error', '未知错误')
                self.completion_error.emit(f"服务器返回错误：{response.status_code} - {error_msg}")

        except requests.exceptions.ConnectionError:
            self.completion_error.emit("无法连接到服务器，请检查服务器是否运行且URL正确。")
        except requests.exceptions.Timeout:
            self.completion_error.emit("服务器响应超时，请尝试增加超时时间或检查服务器性能。")
        except Exception as e:
            self.completion_error.emit(f"补全过程异常：{str(e)}")

# 后续可扩展：分割线程、重建线程（复用上述结构）

class SegmentationThread(QThread):
    """点云分割线程（支持多种方法，返回带颜色的点云）"""
    # 修改信号：返回 带颜色的点云数据（M,3）、颜色数据（M,3）、分割标签
    segmentation_finished = pyqtSignal(np.ndarray, np.ndarray, np.ndarray)
    segmentation_error = pyqtSignal(str)

    def __init__(self, point_cloud_data, segment_method: str):
        super().__init__()
        self.point_cloud_data = point_cloud_data  # (M,3) 原始点云
        self.segment_method = segment_method      # 选择的分割方法

    def run(self):
        try:
            # 调用统一分割接口，获取带颜色的Open3D点云
            colored_pcd, labels = PointCloudSegmentor.segment(
                self.point_cloud_data, self.segment_method
            )
            # 提取点云数据和颜色数据（转为numpy数组）
            points = np.asarray(colored_pcd.points)
            colors = np.asarray(colored_pcd.colors)
            # 发送结果信号
            self.segmentation_finished.emit(points, colors, labels)
        except Exception as e:
            self.segmentation_error.emit(f"分割失败：{str(e)}")

class ReconstructionThread(QThread):
    """点云重建线程（支持多种方法）"""
    # 修改信号：返回 网格对象、顶点数据、重建方法名称
    reconstruction_finished = pyqtSignal(o3d.geometry.TriangleMesh, np.ndarray, str)
    reconstruction_error = pyqtSignal(str)

    def __init__(self, point_cloud_data, reconstruct_method: str):
        super().__init__()
        self.point_cloud_data = point_cloud_data  # (M,3) 原始点云
        self.reconstruct_method = reconstruct_method  # 选择的重建方法

    def run(self):
        try:
            # 调用统一重建接口
            mesh, vertices = PointCloudReconstructor.reconstruct(
                self.point_cloud_data, self.reconstruct_method
            )
            # 发送结果信号（携带重建方法名称）
            self.reconstruction_finished.emit(mesh, vertices, self.reconstruct_method)
        except Exception as e:
            self.reconstruction_error.emit(f"重建失败：{str(e)}")